$TITLE ('RTX-51 TERMINATE SYSTEM CALL')
$SYMBOLS
$NOXREF
$NOCOND
$NOMOD51
$NORB
$PAGELENGTH(80) PAGEWIDTH(110)
;************************************************************************
;*									*
;*    R T X - 5 1  :   DELETE TASK SYSTEM CALL                          *
;*							     		*
;*----------------------------------------------------------------------*
;*                                                                      *
;*    Filename     :   RTXDELET.A51                                     *
;*    Language     :   Keil A-51                                        *
;*    Dev. system  :   Keil uVision2                                    *
;*    Targetsystem :   Any system based upon 8051 up                    *
;*                                                                      *
;*    Purpose      :   Implements the OS_DELETE_TASK system call.       *
;*								     	*
;*								     	*
;*----------------------------------------------------------------------*
;* Rev. |  Released   | Programmer    | Comments                        *
;*----------------------------------------------------------------------*
;*  0.1 |  17.1.1990  | E. Glatz      | Changes for V3.18               *
;*  0.2 |   8.3.1991  | Th. Fischler  | C51 parameter passing           *
;*      |  11.4.1991  |               | More changes for V4.0           *
;*      |  24.5.1991  |               | P2-addressing eliminated &      *
;*      |             |               | adaptions for V4.0              *
;*      |             |               | filename changed to RTXDELET.A51*
;*      |   6.6.1991  | Th. Fischler  | New user_num_table implemented  *
;*      |  18.2.1992  | Th. Fischler  | Proc. REMOVE_RDY: false test    *
;*      |             |               | for table overflow corrected    *
;* 5.00 | 12.10.1994  | E. Glatz      | SEM_DEQUEUE added               *
;* 7.00 | 13.11.2001  | T. Mueller    | Release 7.00                    *
;************************************************************************
;*    Copyright 1991 .. 2001 METTLER  &  FUCHS  AG,  CH-8953 Dietikon   *
;************************************************************************

$INCLUDE (RTXDEBUG.INC)
$INCLUDE (RTXIMASK.INC)

;*----------------------------------------------------------------------*
;*	I M P O R T S
;*----------------------------------------------------------------------*

$INCLUDE (RTXCONST.INC)
$INCLUDE (RTXEXTRN.INC)

;	FROM RTXDISP
EXTRN   CODE (?RTX_REDISPATCH)
;	FROM RTXWAIT
EXTRN   CODE (?RTX_DBLOCK)
;       FROM RTXQUOP
EXTRN   CODE (?RTX_NFL_DEQUEUE, ?RTX_INTSIG_DEQUEUE)
EXTRN   CODE (?RTX_MSG_DEQUEUE, ?RTX_TMO_DEQUEUE, ?RTX_SEM_DEQUEUE)


;*----------------------------------------------------------------------*
;*	E X P O R T S
;*----------------------------------------------------------------------*

PUBLIC  _os_delete_task



;*----------------------------------------------------------------------*
;*	P R O C E D U R E S
;*----------------------------------------------------------------------*

;*----------------------------------------------------------------------*
;*      O S _ D E L E T E _ T A S K
;*----------------------------------------------------------------------*
;*      Terminate a task: de-queue it from all queues, release its	
;*      resources.
;*----------------------------------------------------------------------*
;*      Input:   - R7 : task_id of task to be terminated
;*
;*      Output:  - Completion code returned in R7 :
;*                      = OK       -> successfull deletion
;*                      = NOT_OK   -> task not found
;*----------------------------------------------------------------------*
;*      Internal register usage :
;*         R7 : internal task-number
;*         R6 : task-identifier
;*----------------------------------------------------------------------*

DELETE_FROM_INT_TABLE   MACRO
               LOCAL LOOP, NEXT_INT
               ; Delete Task from Interrupt-Table
               MOV   DPTR, #?RTX_INT_TID_TABLE_BASE
               MOV   R0, #?RTX_MAX_INT_NBR+1
               MOV   ?RTX_TMP0, R6
LOOP:          MOVX  A, @DPTR
               CJNE  A, ?RTX_TMP0, NEXT_INT
               MOV   A, #NIL_TID
               MOVX  @DPTR, A
NEXT_INT:      INC   DPL
	       DJNZ  R0, LOOP
               ENDM


?RTX?_os_delete_task?RTXTERM  SEGMENT CODE
                                 RSEG    ?RTX?_os_delete_task?RTXTERM


_os_delete_task:
               DBG_SYS_ENTRY
               RTX_EXCLUDE_INT
               SETB  ?RTX_SUPERVISOR_MODE       ; Supervisor_mode := on
               ; Check task-number
               MOV   A, R7
               SETB  C
               SUBB  A, #?RTX_MAXTASKN
               JC    EVAL_INTERNAL_NUM
               ; Number is greater than the maximum used task-number
               MOV   R7, #NOT_OK
               JMP   END_TERM

EVAL_INTERNAL_NUM:
               ; Evaluate the internal Task-Number
               MOV   DPH, #HIGH(?RTX_USER_NUM_TABLE)
               MOV   A, #LOW(?RTX_USER_NUM_TABLE)
               ADD   A, R7
               MOV   DPL, A
               ; DPTR -> user_num_table[user_num]
               MOVX  A, @DPTR
               CJNE  A, #NO_TASK, TASK_FOUND
               MOV   R7, #NOT_OK
               JMP   END_TERM                   ; not a valid task

TASK_FOUND:    MOV   R7, A                      ; internal task-num in R7
               MOV   A, #NO_TASK
               MOVX  @DPTR, A                   ; user_num_table[user_num]=NO_TASK
               MOV   DPH, #HIGH(?RTX_TID_TABLE)
               MOV   A, #LOW(?RTX_TID_TABLE)
               ADD   A, R7
               MOV   DPL, A                     ; DPTR-> TID_TABLE[task_num]
               MOVX  A, @DPTR

               ; Check if task wants to terminate itself
               MOV   R6, A                      ; Save TID
               CLR   C
               SUBB  A, ?RTX_RUNNING_TID
               JZ    ITSELF                     ; Jump if yes

               ; Delete task from tid_table
               MOV   A, #NIL_TID
               MOVX  @DPTR, A

               ; Set up pointer to task state
               MOV   A, R7
               RL    A
               RL    A
               ADD   A, #LOW (?RTX_STATE_TABLE)
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_STATE_TABLE)

               ; Check task state if blocked or ready
               MOVX  A, @DPTR                   ; Check first state byte
               ANL   A, #00FH
               JNZ   BLOCKED                    ; Jump if any wait flag is set
               INC   DPL
               MOVX  A, @DPTR                   ; Check second state byte
               JNB   ACC.7, NOT_BLOCKED
               DEC   DPL
               JMP   BLOCKED

NOT_BLOCKED:   ; Task is not blocked for any event
               ; Check if it is suspended
               MOV   A, R6
               CJNE  A, ?RTX_SAVE_INT_TID, RDY
               ; Yes: dequeue it
               MOV   ?RTX_SAVE_INT_TID, #NIL_TID
               DELETE_FROM_INT_TABLE
               MOV   R7, #OK
               JMP   END_TERM

RDY:           JMP   READY
;
;	Running task deletes itself
;
ITSELF:        ; Delete task from tid_table
               MOV   A, #NIL_TID
               MOVX  @DPTR, A
               ; Check if it is a fast task (=driver task)
               JNB   ?RTX_RUNNING_TID.4, NONDR
               ; If yes: possibly unsuspend a
               ; task and/or enter dispatcher
               ; But first delete task from interrupt table
               DELETE_FROM_INT_TABLE
               JMP   ?RTX_DBLOCK
					
NONDR:         ; Proc. is now deallocated
               CLR   ?RTX_PROCESSOR_ALLOCATED
               ; Delete Task from Interrupt-Table
               ; Enter dispatcher
               DELETE_FROM_INT_TABLE
               JMP   ?RTX_REDISPATCH


BLOCKED:       POP   ?RTX_TMP1                  ; Make free 2 bytes of stack
               POP   ?RTX_TMP2                  ; for subroutine call
               MOV   ?RTX_TMP0, R6              ; ?RTX_TMP0 contains task id
                                                ; DPTR->state_table[task no]
               CALL  ?RTX_TMO_DEQUEUE
               ; ?RTX_TMP0, DPTR preserved
	       ; Deq. from non full wait list 
               CALL  ?RTX_NFL_DEQUEUE
	       ; If it was queued for non full then it can not be queued for
	       ; msg and/or sig and/or int
	       JZ    DEQ_DONE

               ; DPTR, ?RTX_TMP0 preserved
	       ; Dequeue from int/sig lists
               CALL  ?RTX_INTSIG_DEQUEUE
               ; DPTR, ?RTX_TMP0 preserved
	       ; Dequeue from msg list
               CALL  ?RTX_MSG_DEQUEUE
               JZ    MSGDEQDONE                 ; Eval ret code if deq done
                                                ; DPTR preserved if no deq done
               CALL  ?RTX_SEM_DEQUEUE           ; ?RTX_TMP0 preserved
MSGDEQDONE:
               ; ?RTX_TMP0 preserved

DEQ_DONE:      PUSH  ?RTX_TMP2                  ; Restore return address
               PUSH  ?RTX_TMP1                  ; to stack
	       DELETE_FROM_INT_TABLE
	       MOV   R7, #OK
               JMP   END_TERM


;
;       Dequeue from ready list
;
READY:		
               POP   ?RTX_TMP1                  ; Make free 2 bytes of stack
               POP   ?RTX_TMP2                  ; for subroutine call
               MOV   ?RTX_TMP0, R6              ; ?RTX_TMP0 contains task id
						; Search for task in readylist
	       CALL  REMOVE_RDY

               PUSH  ?RTX_TMP2                  ; Restore return address
               PUSH  ?RTX_TMP1                  ; to stack
	       ; Check if task found in list
	       JZ    FOUND
	       MOV   R7, #NOT_OK
	       JMP   END_TERM

FOUND:         DELETE_FROM_INT_TABLE
	       MOV   R7, #OK

END_TERM:      JB    ?RTX_REQ_REDISPATCH, RED   ; Redispatch requested ?
					        ; No:
               CLR   ?RTX_SUPERVISOR_MODE       ; Supervisor_mode := off
	       DBG_SYS_EXIT
	       RTX_ALLOW_INT
	       RET				; Return to caller
RED:           CLR   ?RTX_FULL_CONTEXT
               JMP   ?RTX_REDISPATCH



;*----------------------------------------------------------------------*
;*      R E M O V E _ R D Y
;*----------------------------------------------------------------------*
;*      Remove task from ready list. Returns completion status (task
;*      found/ not found).
;*----------------------------------------------------------------------*
;*      Input:   - ?RTX_TMP0 contains task id of task to be dequeued
;*
;*      Output:  - Completion code returned in ACC:
;*                      = 0     if found and dequeued
;*                      = 1     if not found
;*----------------------------------------------------------------------*

?RTX?REMOVE_RDY?RTXTERM  SEGMENT CODE
                         RSEG    ?RTX?REMOVE_RDY?RTXTERM

REMOVE_RDY:
               JB    ?RTX_TMP0.7, PRIO23
               JB    ?RTX_TMP0.6, PRIO1

               ; Set up search pointers and check if list not empty
PRIO0:         MOV   R1, #?RTX_RDY_FIRST0
               MOV   R2, #?RTX_RDY_LAST0
               MOV   ?RTX_TMP3, ?RTX_RDY_LAST0
               MOV   R3, #?RTX_RDY_COUNT0
               MOV   ?RTX_TMP4, #LOW(?RTX_RDY_PRIO0_END - 1)
               MOV   R4, #LOW(?RTX_RDY_PRIO0 - 1)
               MOV   A, ?RTX_RDY_COUNT0
               JNZ   SEARCH_LOOP
               JMP   RDY_NOT_FOUND

PRIO1:         MOV   R1, #?RTX_RDY_FIRST1
               MOV   R2, #?RTX_RDY_LAST1
               MOV   ?RTX_TMP3, ?RTX_RDY_LAST1
               MOV   R3, #?RTX_RDY_COUNT1
               MOV   ?RTX_TMP4, #LOW(?RTX_RDY_PRIO1_END - 1)
               MOV   R4, #LOW(?RTX_RDY_PRIO1 - 1)
               MOV   A, ?RTX_RDY_COUNT1
               JNZ   SEARCH_LOOP
               JMP   RDY_NOT_FOUND

PRIO23:        JB    ?RTX_TMP0.6, PRIO3

PRIO2:         MOV   R1, #?RTX_RDY_FIRST2
               MOV   R2, #?RTX_RDY_LAST2
               MOV   ?RTX_TMP3, ?RTX_RDY_LAST2
               MOV   R3, #?RTX_RDY_COUNT2
               MOV   ?RTX_TMP4, #LOW(?RTX_RDY_PRIO2_END - 1)
               MOV   R4, #LOW(?RTX_RDY_PRIO2 - 1)
               MOV   A, ?RTX_RDY_COUNT2
               JNZ   SEARCH_LOOP
               JMP   RDY_NOT_FOUND

PRIO3:         MOV   R1, #?RTX_RDY_FIRST3
               MOV   R2, #?RTX_RDY_LAST3
               MOV   ?RTX_TMP3, ?RTX_RDY_LAST3
               MOV   R3, #?RTX_RDY_COUNT3
               MOV   ?RTX_TMP4, #LOW(?RTX_RDY_PRIO3_END - 1)
               MOV   R4, #LOW(?RTX_RDY_PRIO3 - 1)
               MOV   A, ?RTX_RDY_COUNT3
               JNZ   SEARCH_LOOP
               JMP   RDY_NOT_FOUND

SEARCH_LOOP:   ; DPL is search_ptr
               ; search_ptr=first_ptr
               MOV   DPH, #HIGH(?RTX_SYS_PAGE)
               MOV   A, @R1
               MOV   DPL, A
               ; Get element 1
               MOVX  A, @DPTR
               ; Inc (search_ptr)
               XCH   A, DPL
               CJNE  A, ?RTX_TMP4, TEMPL1       ; Check for overflow
               MOV   A, R4
TEMPL1:        INC   A
               ; first_ptr=search_ptr
               MOV   @R1, A
               ; Get back el 1
               XCH   A, DPL
WHILE_TST:     ; Check if el 1 = ?RTX_TMP0
               CJNE  A, ?RTX_TMP0, WHILE_LOOP
               ; Element found !
               ; Dec (list_count)
               MOV   A, R3
               MOV   R0, A
               DEC   @R0
               ; Return 'element found'
               CLR   A
               RET

WHILE_LOOP:    ; Store element 1 in B
               MOV   B, A
               ; Get element 2
               MOVX  A, @DPTR
               ; Store el 1 at search_ptr
               XCH   A, B                       ; ACC=el 1, B=el 2
               MOVX  @DPTR, A
               ; Check if search_ptr=last_ptr
               MOV   A, DPL
               CJNE  A, ?RTX_TMP3, NEQ
               ; Yes: inc (last_ptr)
               MOV   A, R2
               MOV   R0, A
               MOV   A, @R0
               CJNE  A, ?RTX_TMP4, TEMPL2       ; Check for overflow
               MOV   A, R4
TEMPL2:        INC   A
               MOV   @R0, A

               ; Return 'not found'
RDY_NOT_FOUND: MOV   A, #1
               RET

NEQ:           ; Inc (search_ptr)
               CJNE  A, ?RTX_TMP4, TEMPL3       ; Check for overflow
               MOV   A, R4
TEMPL3:        INC   A
               MOV   DPL, A
               ; el 1 = el 2
               MOV   A, B
               JMP   WHILE_TST
                                                
;
;   END OF MODULE
;
	END
